/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package prvydevw.servlet;

import com.google.gson.Gson;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import prvydevw.entity.Subject;
import prvydevw.manager.ServiceFailureException;
import prvydevw.manager.SubjectManager;

/**
 *
 * @author ivo
 */
public class SubjectsServlet extends HttpServlet {

    private static final String LIST_JSP = "/subjects.jsp";
    
    private Stack<Notification> notifications = new Stack<Notification>();
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        String action = request.getPathInfo();
        List<Notification> notifs = new ArrayList<Notification>();
        
        while(!notifications.empty()) {
            notifs.add(notifications.pop());
        }
        
        request.setCharacterEncoding("utf-8");
        request.setAttribute("notifications", notifs);
        
        if (action.equals("/list")) {
            listAction(request, response);
        }
        else if (action.equals("/save")) {
            saveAction(request, response);
        }
        else if (action.equals("/delete")) {
            deleteAction(request, response);
        }
        else {
            response.sendError(404, "Page not found");
        }
    }
    
    private void listAction(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        SubjectManager subjectManager = (SubjectManager) getServletContext().getAttribute("subjectManager");
        
        List<Subject> subjects = subjectManager.findAllSubjects();
        
        request.setAttribute("subjects", subjects);
        
        request.getRequestDispatcher(LIST_JSP).forward(request, response);
    }
    
    private void saveAction(HttpServletRequest request, HttpServletResponse response) throws IOException
    {
        Subject subject = getSubjectFromRequest(request);
        
        if (subject == null) {
            manageRedirect(request, response, subject);
            
            return;
        }
        
        SubjectManager manager = (SubjectManager) getServletContext().getAttribute("subjectManager");
        
        try {
            if (subject.getId() == null) {
                manager.createSubject(subject);
            }
            else {
                manager.updateSubject(subject);
            }
            
            notifications.add(new Notification("success", "Subjekt byl úspěšně uložen"));
        }
        catch (ServiceFailureException e) {
            notifications.add(new Notification("error", "Vyskytla sa chyba při ukladaní subjektu"));
            
            Logger.getLogger(PaymentsServlet.class.getName()).log(Level.SEVERE, "Error saving subject", e);
        }
        
        manageRedirect(request, response, subject);
    }
    
    private void deleteAction(HttpServletRequest request, HttpServletResponse response) throws IOException
    {
        Long id;
        String subjectId = request.getParameter("subject");
        
        if (subjectId == null || subjectId.isEmpty()) {
            notifications.add(new Notification("error", "Musí být zadán subjekt pro odstranění"));
            
            manageRedirect(request, response, null);
            return;
        }
        
        try {
            id = Long.parseLong(subjectId);
        }
        catch (NumberFormatException e) {
            notifications.add(new Notification("error", "Neplatný subjekt"));
            
            manageRedirect(request, response, null);
            return;
        }
        
        SubjectManager manager = (SubjectManager) getServletContext().getAttribute("subjectManager");
        Subject subject = manager.findSubject(id);
        
        if (subject == null) {
            notifications.add(new Notification("error", "Subjekt nebyl nalezen"));
            
            manageRedirect(request, response, subject);
            return;
        }
        
        try {
            manager.deleteSubject(subject);
            
            notifications.add(new Notification("success", "Subjekt byl úspěšně smazán"));
        }
        catch (ServiceFailureException e) {
            notifications.add(new Notification("error", "Vyskytla sa chyba při mazaní subjektu"));
            
            Logger.getLogger(PaymentsServlet.class.getName()).log(Level.SEVERE, "Error deleting subject", e);
        }
        
        manageRedirect(request, response, subject);
    }
    
    private Subject getSubjectFromRequest(HttpServletRequest request)
    {   
        Map<String, String[]> requestParams = request.getParameterMap();
        String key = getSubjectKey(requestParams);
        Map<String, String> params = getSubjectParams(requestParams, key);
        
        String name = params.get("name");
        String regId = params.get("ico");
        String accountNumber = params.get("account");
        
        if (name == null || name.isEmpty()) {
            notifications.add(new Notification("error", "Jméno musí být vyplněno"));
                
            return null;
        }
        
        if (accountNumber == null || accountNumber.isEmpty()) {
            notifications.add(new Notification("error", "Číslo účtu musí být vyplněno"));
                
            return null;
        }
        
        Long id = null;
        String subjectId = params.get("id");
        
        if (subjectId != null && !subjectId.isEmpty()) {
            try {
                id = Long.parseLong(subjectId);
            }
            catch(NumberFormatException e) {
                notifications.add(new Notification("error", "ID subjektu musí být celé číslo"));
                
                return null;
            }
        }
        
        Subject subject = new Subject();
        subject.setId(id);
        subject.setName(name);
        subject.setAccountNumber(accountNumber);
        subject.setRegId(regId);
        
        return subject;
    }
    
    private Map<String, String> getSubjectParams(Map<String, String[]> params, String key)
    {
        Map<String, String> paymentParams = new HashMap<String, String>();

        for (Map.Entry<String, String[]> entry : params.entrySet()) {
            String name = entry.getKey();

            if (name.endsWith("["+key+"]")) {
                String paramKey = name.substring(0, name.indexOf('['));
                
                paymentParams.put(paramKey, entry.getValue()[0]);
            }
        }
        
        return paymentParams;
    }
    
    private String getSubjectKey(Map<String, String[]> params)
    {
        for (Map.Entry<String, String[]> entry : params.entrySet()) {
            String name = entry.getKey();
            
            if (name.startsWith("send[")) {
                String key = name.substring(name.indexOf('[') + 1, name.indexOf(']'));
                
                return key;
            }
        }
        
        return null;
    }
    
    private boolean isAjaxRequest(HttpServletRequest request) {
        return request.getHeader("X-Requested-With") != null && request.getHeader("X-Requested-With").equals("XMLHttpRequest");
    }
    
    private void manageRedirect(HttpServletRequest request, HttpServletResponse response, Subject subject) throws IOException
    {
        response.setCharacterEncoding("utf-8");
        
        if (isAjaxRequest(request)) {
            Gson gson = new Gson();
            
            response.getWriter().print(gson.toJson(new JsonResponse(notifications, subject)));
        }
        else {
            response.sendRedirect("list");
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
